package com.tiger.log.core.processing.business;

import com.tiger.log.common.annotation.business.form.FormCollect;
import com.tiger.log.common.annotation.business.json.JsonCollect;
import com.tiger.log.common.constant.EnableProperties;
import com.tiger.log.common.constant.LogConstant;
import com.tiger.log.common.constant.TokenProperties;
import com.tiger.log.common.entity.SysRecordLog;
import com.tiger.log.common.enums.ProcessType;
import com.tiger.log.common.enums.Result;
import com.tiger.log.common.exception.member.EnumsNotMatchException;
import com.tiger.log.common.util.MeUtil;
import com.tiger.log.core.parse.ProceedParse;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @ClassName CommonProcessing
 * @Description TODO
 * @Author huxuehao
 **/
@Component
public class CommonProcessing {

    private final ProceedParse proceedParse;
    private final TokenProperties tokenProperties;
    private final EnableProperties enableProperties;

    public CommonProcessing(ProceedParse proceedParse, TokenProperties tokenProperties, EnableProperties enableProperties) {
        this.proceedParse = proceedParse;
        this.tokenProperties = tokenProperties;
        this.enableProperties = enableProperties;
    }

    /**
     * 验证是否非法
     */
    public boolean isIllegal(ProceedingJoinPoint joinPoint, ProcessType type) {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        String code;
        switch (type) {
            case JSON:
                code = method.getAnnotation(JsonCollect.class).code();
                return !(enableProperties.isOpen() || enableProperties.getExcludeCodes().contains(code));
            case FORM:
                code = method.getAnnotation(FormCollect.class).code();
                return !(enableProperties.isOpen() || enableProperties.getExcludeCodes().contains(code));
            default:
                throw new EnumsNotMatchException("ProcessType匹配失败");
        }
    }

    /**
     * 从Collect注解中获取必要的内容填充SysRecordLog
     */
    public void fillRecordCollect(@NotNull SysRecordLog recordLog, ProceedingJoinPoint joinPoint, ProcessType type) {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        switch (type) {
            case JSON :
                JsonCollect json = method.getAnnotation(JsonCollect.class);
                recordLog.setOperationType(json.type().toString());
                recordLog.setBusinessClassify(json.classify());
                recordLog.setBusinessCode(json.code());
                recordLog.setComment(json.comment());
                break;
            case FORM :
                FormCollect form = method.getAnnotation(FormCollect.class);
                recordLog.setOperationType(form.type().toString());
                recordLog.setBusinessClassify(form.classify());
                recordLog.setBusinessCode(form.code());
                recordLog.setComment(form.comment());
                break;
            default:
                throw new EnumsNotMatchException("ProcessType匹配失败");
        }
        recordLog.setId(MeUtil.nextId());
    }

    /**
     * 根据请求体中进行填充
     */
    public void fillRecordRequest(@NotNull SysRecordLog recordLog) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert requestAttributes != null;
        HttpServletRequest request = requestAttributes.getRequest();

        recordLog.setRequestAddress(request.getRemoteAddr());
        recordLog.setRequestUri(request.getRequestURI());
        recordLog.setRequestTime(MeUtil.currentDatetime(LogConstant.TIME_FORMAT));
        recordLog.setUserAgent(request.getHeader("User-Agent"));
        recordLog.setUserCode(proceedParse.userCodeByTokenParse(request.getHeader(tokenProperties.getTokenKey())));
    }


    /**
     * 根据执行结果填充SysRecordLog
     */
    public void fillRecordResult(@NotNull SysRecordLog sysRecordLog, Object res, boolean isCatch) {
        if (res == null && isCatch) {
            sysRecordLog.setOperationResult(Result.FAIL.toString());
        } else {
            sysRecordLog.setOperationResult(proceedParse.executeResultParse(res).toString());
        }
    }
}
